package com.awspaas.user.apps.cpq.controller;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.regex.Pattern;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

import com.actionsoft.bpms.bo.engine.BO;
import com.actionsoft.bpms.commons.mvc.view.ResponseObject;
import com.actionsoft.bpms.server.UserContext;
import com.actionsoft.exception.BPMNError;
import com.actionsoft.sdk.local.SDK;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

public class CPQ_GetPlasticWeightWeb {
	 private static final String REGEX = "^-?[0-9]+(\\.[0-9]+)?([\\+\\-\\*/]-?[0-9]+(\\.[0-9]+)?)*$"; // 简化的正则
	public String getPlasticWeight(UserContext userContext, String bindId,String datas) throws Exception {
	try {
		JSONArray dataList=JSONObject.parseArray(datas);						
		List<BO> bos=SDK.getBOAPI().query("BO_EU_CPQ_COMPONENT_PART_PROPERTIES_GRID").bindId(bindId).list();
		Map<String, BO> pMap = new HashMap<String, BO>();
		if(bos.size()>0) {
			for (BO bo : bos) {
				pMap.put(bo.getId(), bo);
			}
		}
		if(dataList.size()>0) {
			for (Object object : dataList) {
				JSONObject json=(JSONObject) object;
				String 	jsgs=json.getString("ZLJSJZ");
				String 	hgl=json.getString("HGL").isEmpty()?"0":json.getString("HGL");
				if(null!=jsgs&&!jsgs.isEmpty()) {
					if(isValid(jsgs)) {//判断是否是正确的四则运算
						// 创建ScriptEngineManager对象
				        ScriptEngineManager manager = new ScriptEngineManager();
				        // 获取JavaScript引擎
				        ScriptEngine engine = manager.getEngineByName("JavaScript");
				        // 计算表达式的值
			            Object result = engine.eval(jsgs);
			            // 尝试将Object转换为Double
			            String doubleValue = String.valueOf(result);

			            // 使用BigDecimal来格式化数字，保留两位小数
			            BigDecimal bd = new BigDecimal(doubleValue);
			            BigDecimal hg = new BigDecimal(hgl);
			            BigDecimal wg= bd.divide(hg,4);
			            wg = wg.setScale(4, RoundingMode.DOWN); // 直接截断到两位小数
			             /**
			              * 计算三个价格：期货、临时、入库，如果其中某一个价格没有，则按照规则进行价格查询，
			              * 规则为：期货、临时、入库
			              * 
			              */			            			            
			            String CLDJ=json.getString("CLDJ").isEmpty()?"0":json.getString("CLDJ");//期货价
			           
			            BigDecimal price1 = new BigDecimal(CLDJ);
			            BigDecimal totalPrice1=new BigDecimal("0");
			           
			            //计算期货价总价
			            if(price1.compareTo(BigDecimal.ZERO)==0) {	            	
			            			throw new BPMNError("003","材料名称为："+json.getString("MC")+"的材料中期货价格没有，请填写后进行计算。");
			            }else {
			            	totalPrice1=wg.multiply(price1);
			            }
			           
			            //判断数据是否已存在，如果存在进行更新如果不存在则创建数据
			            List<BO> bos2=new ArrayList<>();
			            if(pMap.containsKey(json.getString("ID"))) {
			            	BO bo=pMap.get(json.getString("ID"));
			            	bo.set("ZL", wg);
			            	bo.set("CLF", totalPrice1);
			            	
			            	SDK.getBOAPI().update("BO_EU_CPQ_COMPONENT_PART_PROPERTIES_GRID", bo);
			            }else {
			            	BO bo=new BO();
			            	bo.set("MC",json.getString("MC") );
			            	bo.set("BM",json.getString("BM") );
			            	bo.set("LX", json.getString("LX"));
			            	bo.set("XH", json.getString("XH"));
			            	bo.set("DW",json.getString("DW") );
			            	bo.set("CLDJ", CLDJ);
			            	
			            	bo.set("ZLJSJZ", jsgs);
			            	bo.set("HGL",hgl );
			            	bo.set("TJ",json.getString("TJ") );
			            	bo.set("ZL", wg);
			            	bo.set("CLF", totalPrice1);
			            	
			            	bos2.add(bo);
			            }
			            if(bos2.size()>0) {
			            	SDK.getBOAPI().create("BO_EU_CPQ_COMPONENT_PART_PROPERTIES_GRID", bos2, bindId, userContext.getUID());
			            }
			            
			           // bo.set("ZL", wg);
			           // bo.set("CLF", totalPrice);
			           //SDK.getBOAPI().update("BO_EU_CPQ_COMPONENT_PART_PROPERTIES_GRID", bo);
					}
					
					 
				   }
				
			}
		}
		
		
		 ResponseObject ro = ResponseObject.newOkResponse();
		   return ro.toString();
	
	} catch (Exception e) {
	throw  e;
	}
	
	}

public static boolean isValid(String expression) {
    // 检查空字符串
    if (expression == null || expression.isEmpty()) {
        return false;
    }

    // 检查无效字符
    if (!expression.matches("^[\\d+\\-*/().]+$")) {
        return false;
    }

    // 检查括号匹配
    if (!checkParentheses(expression)) {
        return false;
    }

    // 检查首尾字符
    if (!checkFirstAndLastChar(expression)) {
        return false;
    }

    // 检查运算符位置和数字有效性
    if (!checkOperatorsAndNumbers(expression)) {
        return false;
    }

    return true;
}

private static boolean checkParentheses(String s) {
    Stack<Character> stack = new Stack<>();
    for (char c : s.toCharArray()) {
        if (c == '(') {
            stack.push(c);
        } else if (c == ')') {
            if (stack.isEmpty() || stack.pop() != '(') {
                return false;
            }
        }
    }
    return stack.isEmpty();
}

private static boolean checkFirstAndLastChar(String s) {
    char first = s.charAt(0);
    // 首字符可以是数字、负号、左括号
    if (!(Character.isDigit(first) || first == '(' || first == '-')) {
        return false;
    }
    // 如果首字符是负号，后面必须接数字或左括号
    if (first == '-' && s.length() > 1) {
        char next = s.charAt(1);
        if (!(Character.isDigit(next) || next == '(')) {
            return false;
        }
    }

    char last = s.charAt(s.length() - 1);
    // 尾字符必须是数字或右括号
    if (!(Character.isDigit(last) || last == ')')) {
        return false;
    }
    return true;
}

private static boolean checkOperatorsAndNumbers(String s) {
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (isOperator(c)) {
            // 处理运算符
            if (c == '-') {
                // 可能是一元或二元
                if (i == 0) {
                    // 一元运算符，后面必须跟数字或左括号
                    if (i + 1 >= s.length() || (!Character.isDigit(s.charAt(i + 1)) && s.charAt(i + 1) != '(')) {
                        return false;
                    }
                } else {
                    char prev = s.charAt(i - 1);
                    if (prev == '(' || isOperator(prev)) {
                        // 一元运算符，后面必须跟数字或左括号
                        if (i + 1 >= s.length() || (!Character.isDigit(s.charAt(i + 1)) && s.charAt(i + 1) != '(')) {
                            return false;
                        }
                    } else {
                        // 二元运算符，检查前后是否合法
                        if (i == s.length() - 1) {
                            return false;
                        }
                        char next = s.charAt(i + 1);
                        if (!(Character.isDigit(prev) || prev == ')') || 
                            !(Character.isDigit(next) || next == '(')) {
                            return false;
                        }
                    }
                }
            } else {
                // 其他运算符必须是二元
                if (i == 0 || i == s.length() - 1) {
                    return false;
                }
                char prev = s.charAt(i - 1);
                char next = s.charAt(i + 1);
                if (!(Character.isDigit(prev) || prev == ')') || 
                    !(Character.isDigit(next) || next == '(')) {
                    return false;
                }
            }
        } else if (c == '(') {
            // 左括号后面只能是数字、左括号或一元负号
            if (i < s.length() - 1) {
                char next = s.charAt(i + 1);
                if (!(Character.isDigit(next) || next == '(' || next == '-')) {
                    return false;
                }
            } else {
                return false; // 左括号不能在末尾
            }
        } else if (c == ')') {
            // 右括号后面只能是运算符或右括号
            if (i < s.length() - 1) {
                char next = s.charAt(i + 1);
                if (!(isOperator(next) || next == ')')) {
                    return false;
                }
            }
        }
    }
    return true;
}

private static boolean isOperator(char c) {
    return c == '+' || c == '-' || c == '*' || c == '/';
}
}
